package com.breaktian.network.http;

import android.content.Context;
import android.support.annotation.Nullable;
import android.text.TextUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.breaktian.assemble.jni.Native;
import com.breaktian.assemble.security.Md5Util;
import com.breaktian.assemble.security.des.ThreeDesUtil;
import com.breaktian.network.util.Utils;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * Created by keke.tian on 2018/4/25.
 */

public class Cache {

    private static File mCacheDir;
    private static int MAX_SIZE = 10*1024*1024;//10MB
    private static long MAX_EXPIRE = 3*24*60*60*1000;//3天
    //24字节
    static byte[] KEY = Native.getThreeDesKey();

    private File mCacheFile;

    public Cache(String key){
        if (mCacheDir != null && !TextUtils.isEmpty(key)) {
            mCacheFile = new File(mCacheDir, Md5Util.encrypt16(key));
            if(!mCacheFile.exists()) try {
                mCacheFile.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public boolean write(String content){
        boolean result = false;
        if(!TextUtils.isEmpty(content)&&mCacheFile.exists()){
            // 加密
            String encryptContent = ThreeDesUtil.encrypt(content, KEY);
            result = Utils.write(mCacheFile,encryptContent);
        }
        return result;
    }

    public String read(){
        String result = "";
        if(mCacheFile.exists()){
            String content = Utils.read(mCacheFile);
            // 解密
            result = ThreeDesUtil.decrypt(content,KEY);
        }
        return result;
    }

    @Nullable
    <T> T read(Class<T> cls) {
        String text = read();
        if (TextUtils.isEmpty(text)) return null;
        try {
            return JSON.parseObject(text, cls);
        } catch (Exception e) {
            return null;
        }
    }

    @Nullable
    <T> T read(TypeReference<T> reference) {
        String text = read();
        if (TextUtils.isEmpty(text)) return null;
        try {
            return JSON.parseObject(text, reference);
        } catch (Exception e) {
            return null;
        }
    }


    static void init(Context context,int maxSize,long maxExpire){
        if(context==null){
            return;
        }
        mCacheDir = new File(context.getCacheDir(),"http");
        if(!mCacheDir.exists()){
            mCacheDir.mkdirs();
        }
        MAX_SIZE = maxSize;
        MAX_EXPIRE = maxExpire;
    }

    static void clearCache(){
        new ClearCacheTask(MAX_SIZE, MAX_EXPIRE).start();
    }

    static class ClearCacheTask extends Thread{

        private static final float SIZE_HOLD = .75f;
        private final int maxSize;
        private final long maxExpire;

        public ClearCacheTask(int maxSize, long maxExpire){
            this.maxSize = maxSize;
            this.maxExpire = maxExpire;
        }

        @Override
        public void run() {
            if(mCacheDir==null||!mCacheDir.exists()){
                return;
            }
            long size = 0;
            long currentTime = System.currentTimeMillis();
            long sizeHold = (long)(maxSize * SIZE_HOLD);
            List<File> list = new ArrayList<>();
            File[] files = mCacheDir.listFiles();
            for (File file:files) {
                if (".".equals(file.getName()) || "..".equals(file.getName())) continue;
                if(currentTime-file.lastModified()<maxExpire||!file.delete()){
                    size += file.length();
                    list.add(file);
                }
            }

            if (size <= sizeHold) return;
            Collections.sort(list, new Comparator<File>() {
                @Override
                public int compare(File o1, File o2) {
                    if (o1.lastModified() == o2.lastModified()) return 0;
                    return o1.lastModified() < o2.lastModified() ? -1 : 1;
                }
            });

            long deleteSize = size - sizeHold;
            size = 0;
            for (File file : list) {
                long length = file.length();
                if (file.delete()) {
                    size += length;
                }
                if (size > deleteSize) break;
            }

        }
    }

}
